package com.lucun.es_transaction.service.impl;

import com.lucun.es_transaction.entity.*;
import com.lucun.es_transaction.mapper.*;
import com.lucun.es_transaction.service.UserService;
import com.lucun.es_transaction.util.*;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.DigestUtils;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.text.SimpleDateFormat;
import java.time.Duration;
import java.util.Date;
import java.util.List;
import java.util.Random;

@Service
public class UserServiceImpl implements UserService {
    @Resource
    private UserMapper userMapper;
    @Resource
    private UserLogMapper logMapper;
    @Resource
    private AuthenticationMapper authenticationMapper;
    @Autowired
    private RedisTemplate<String, String> redisTemplate;

    @Autowired
    private RedisUtil redisUtil;

    /**
     * 用户登录
     */
    @Transactional
    @Override
    public JsonResult<?> login(User user){
        if(ObjectUtils.isEmpty(user)){
            throw new BaseException("登录内容为空");
        }
        String phone1 = user.getPhone();
        if(ObjectUtils.isEmpty(phone1)){
            throw new BaseException("登录手机号不能为空");
        }
        //        判断用户输入的值是否为手机号码
        boolean b = new RegexValidateUtil().checkMobilePhone(phone1);
        if (!b){
            throw new BaseException("登录手机号格式不对");
        }
        String password = user.getPassword();
        if(StringUtils.isBlank(password)){
            throw new BaseException("密码为空");
        }
        if(user.getPassword().length()<6||user.getPassword().length()>18){
            throw new BaseException("密码长度应在6-18之间");
        }
        User u = userMapper.selectByPhone(phone1);
        if (ObjectUtils.isEmpty(u)){
            throw new BaseException("该手机号用户不存在");
        }
        //获取随机盐
        String salt= u.getSalt();
        //数据库的密码
        String password2= u.getPassword();
        //把输入的面进行加密
        String password1 = PwdTool.getHMAC(password,salt);
//        用户输入密码和数据库中的密码进行比对
        if (!password1.equals(password2)){
            throw new BaseException("密码不对");
        }
        //获取token
        String token = JwtUtil.sign(u);
//        用户登录成功则生成日志
        UserLog log = new UserLog();
        String time=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date());
        log.setCreateTime(new Date());
        log.setLogType((byte) 4);
        log.setUserId(u.getId());
        log.setLogName("账号" + u.getNumber() + "在" + time + "登录成功");
        log.setLogStatus((byte) 1);
        logMapper.insertSelective(log);
        return new JsonResult<>("200","登录成功",u,token);
    }

    /**
     * 用户注册账号
     */
    @Override
    public JsonResult<?> insertSelective(User user){
        if(ObjectUtils.isEmpty(user)){
            throw new BaseException("注册内容不能为空");
        }
        /*
         * 用户编号自生成
         * */
        int num1 = 0;
        Random random1 = new Random();
        StringBuffer stringBuffer1 = new StringBuffer();
        for (int i = 0; i < 7; i++) {
            num1 = random1.nextInt(9);
            stringBuffer1.append(num1);
        }
        user.setNumber(stringBuffer1.toString());

        if(user.getNumber().length()<6||user.getNumber().length()>12){
            throw new BaseException("账号长度应在6-12之间");
        }
        if(StringUtils.isBlank(user.getPassword())){
            throw new BaseException("密码不能为空");
        }
        if(user.getPassword().length()<6||user.getPassword().length()>18){
            throw new BaseException("密码长度应在6-18之间");
        }
        User userTest = new User();
        userTest.setUsername(user.getUsername());
        User username = userMapper.selectUserByAll(userTest);
        if(!ObjectUtils.isEmpty(username)){
            throw new BaseException("该用户名已被注册");
        }
        String phone = user.getPhone();
        boolean phone1 = new RegexValidateUtil().checkMobilePhone(phone);
        if (!phone1){
            throw new BaseException("手机号格式不对");
        }
        User user1 = new User();
        user1.setPhone(user.getPhone());
        User userPhone = userMapper.selectUserByAll(user1);
        if(!ObjectUtils.isEmpty(userPhone)){
            throw new BaseException("该手机号已被绑定过用户了");
        }
        if(StringUtils.isBlank(user.getPassword())){
            throw new BaseException("密码设置为空,长度在6-18位");
        }
//        生成随机盐
        String salt = PwdTool.getRandomSalt();
//        登录密码MD5加密+随机盐
        String password = PwdTool.getHMAC(user.getPassword(),salt);
        user.setPassword(password);
        user.setSalt(salt);
        user.setCreateTime(new Date()); //获取当前时间
        //判断用户注册成功
        int i = userMapper.insertSelective(user);
//        生成注册日志
        UserLog log = new UserLog();
        String time=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date());
        log.setCreateTime(new Date());
        log.setLogType((byte) 1);
        log.setUserId(user.getId());
        if(i>0) {
            log.setLogName("账号" + user.getNumber() + "在" + time + "注册成功");
            log.setLogStatus((byte) 1);
            logMapper.insertSelective(log);
        }
        return new JsonResult<>("200","注册成功",user);
    }

    @Override
    public List<User> selectAll() {
        return userMapper.selectAll();
    }

    /**
     * 修改
     */
    @Transactional
    @Override
    public JsonResult<?> updateByPrimaryKeySelective(User user, HttpServletRequest request){
        if(ObjectUtils.isEmpty(user)){
            throw new BaseException("获取用户信息失败");
        }
        int idByToken = JwtUtil.getIdByToken(request);
        if(ObjectUtils.isEmpty(idByToken)){
            throw new BaseException("解析token失败");
        }
//        获取用户信息
        User user1 = userMapper.selectByPrimaryKey(idByToken);
//        校验用户信息是否一致
        if(ObjectUtils.isEmpty(user1)){
            throw new BaseException("用户不存在");
        }
//        校验手机号是否被别的账号绑定
        if(!StringUtils.isBlank(user.getPhone())){
            boolean b = new RegexValidateUtil().checkMobilePhone(user.getPhone());
            if(!b){
                throw new BaseException("手机格式不正确");
            }
            User user2 = new User();
            user2.setPhone(user.getPhone());
            User user3 = userMapper.selectUserByAll(user2);
            if(!ObjectUtils.isEmpty(user3)){
                throw new BaseException("手机号已被别的账号绑定");
            }
            boolean codeCompare = redisUtil.selectCodeCompare(user.getPhone(), user.getCode());
            if(!codeCompare){
                throw new BaseException("验证码不正确");
            }
        }
//        校验用户名是否唯一
        if(!StringUtils.isBlank(user.getUsername())){
            if(user.getUsername().length()>12||user.getUsername().length()<1){
                throw new BaseException("用户名的长度为1-12");
            }
            User user2 = new User();
            user2.setUsername(user.getUsername());
            User userName = userMapper.selectUserByAll(user2);
            if(!ObjectUtils.isEmpty(userName)){
                throw new BaseException("用户名已存在");
            }
        }
//        校验修改密码和原密码重复
        String passwordMd5="";
        if(!StringUtils.isBlank(user.getPassword())){
            if(user.getPassword().length()<6||user.getPassword().length()>18){
                throw new BaseException("密码长度在6-18位");
            }
//            根据ID查询salt随机盐+密码
            User user4 = userMapper.selectByPrimaryKey(idByToken);
            String salt = user4.getSalt();
            String passwordData = user4.getPassword();
//            用户键入的密码加密
            String password = user.getPassword();
            String passwordSalt=salt+password;
            passwordMd5=DigestUtils.md5DigestAsHex(passwordSalt.getBytes());
            if(passwordMd5.equals(passwordData)){
                throw new BaseException("密码重复");
            }
        }
        user.setId(idByToken);
        user.setPassword(passwordMd5);
        user.setUpdateTime(new Date());
        int i = userMapper.update(user);
//        生成修改用户信息日志
        UserLog log = new UserLog();
        String time=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date());
        log.setCreateTime(new Date());
        log.setLogType((byte) 3);
        log.setUserId(idByToken);
        if(i>0){
            log.setLogName("账号"+user1.getNumber()+"在"+time+"修改成功");
            log.setLogStatus((byte) 1);
            logMapper.insertSelective(log);
        }else{
            log.setLogName("账号"+user1.getNumber()+"在"+time+"修改失败");
            log.setLogStatus((byte) 0);
            logMapper.insertSelective(log);
        }
        User user2 = userMapper.selectByPrimaryKey(idByToken);
        if(i>0){
            return new JsonResult<>("200","修改成功",user2);
        }else{
            return new JsonResult<>("500","修改失败",user2);
        }
    }
    /**
     * 用户注销功能
     */
    @Transactional
    @Override
    public JsonResult<?> delete(HttpServletRequest request){
        int idByToken = JwtUtil.getIdByToken(request);
        if(ObjectUtils.isEmpty(idByToken)){
            throw new BaseException("解析token失败");
        }
//        获取用户信息
        User user1 = userMapper.selectByPrimaryKey(idByToken);
        if(ObjectUtils.isEmpty(user1)){
            throw new BaseException("该用户不存在");
        }
        int i = userMapper.deleteByPrimaryKey(idByToken);
//        注销成功后根据number删除个人信息
        String number = JwtUtil.getNumberByToken(request);
        if (StringUtils.isBlank(number)){
            throw new BaseException("解析number失败");
        }
        authenticationMapper.deleteByNumber(number);
        UserLog log = new UserLog();
        String time=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date());
        log.setCreateTime(new Date());
        log.setUserId(idByToken);
        log.setLogType((byte) 2);
        if(i>0){
            log.setLogName("账号"+user1.getNumber()+"在"+time+"注销成功");
            log.setLogStatus((byte) 1);
            logMapper.insertSelective(log);
        }else {
            log.setLogName("账号"+user1.getNumber()+"在"+time+"注销失败");
            log.setLogStatus((byte) 0);
            logMapper.insertSelective(log);
        }
        if(i>0){
            return new JsonResult<>("200","注销成功",user1);
        }else{
            return new JsonResult<>("500","注销失败",user1);
        }

    }

    /**
     * 生成验证码
     */
    @Override
    public JsonResult<?> insertCode(User user){
//        生成验证码
        Random random = new Random();
        StringBuffer stringBuffer = new StringBuffer();
        for (int i = 0; i < 4; i++) {
            int randomCode=random.nextInt(9);
            stringBuffer.append(randomCode);
        }
        String randomCode=stringBuffer.toString();
        redisTemplate.opsForValue().set(user.getPhone(), randomCode);
//        配置验证码有效时间
        redisTemplate.expire(user.getPhone(), Duration.ofMinutes(5));
//        获取验证码
        String code=redisTemplate.opsForValue().get(user.getPhone());
        return new JsonResult<>("200","请求成功",code);
    }

    /*
     * 根据number查询
     * */
    @Override
    public JsonResult<?> selectByNmuber(HttpServletRequest request) {
        String tokenNumber = JwtUtil.getNumberByToken(request);
        return new JsonResult<>("200","根据编号查询成功",
                userMapper.findByNumber(tokenNumber)
        );
    }

}
